package com.firmboy.spring_axis2.config;

import org.apache.axis2.AxisFault;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.deployment.DeploymentEngine;
import org.apache.axis2.deployment.DeploymentException;
import org.apache.axis2.deployment.RepositoryListener;
import org.apache.axis2.deployment.WarBasedAxisConfigurator;
import org.apache.axis2.deployment.repository.util.ArchiveReader;
import org.apache.axis2.deployment.repository.util.DeploymentFileData;
import org.apache.axis2.description.AxisService;
import org.apache.axis2.description.AxisServiceGroup;
import org.apache.axis2.engine.AxisConfiguration;
import org.apache.axis2.i18n.Messages;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.servlet.ServletConfig;
import javax.xml.stream.XMLStreamException;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;

/**
 * @author firmboy
 * @create 2018-06-08 下午7:13
 **/
public class WarBasedAxisConfiguratorExport extends WarBasedAxisConfigurator {

    private static final Log log = LogFactory.getLog(WarBasedAxisConfiguratorExport.class);
    private ServletConfig config;

    /**
     * Default constructor for configurator.
     * This determines the axis2.xml file to be used from the init parameters for the AxisServlet in the web.xml.
     * The order of initialization is according the the following precedence:
     * <ul>
     * <li>If the parameter axis2.xml.path is present, the value is webapp relative path to be used as the location to the axis2.xml file.
     * <li>Otherwise, if the parameter axis2.xml.url is present, the URL is used as the location to the axis2.xml file.
     * <li>Otherwise, when both of the above init parameters are not present, file is attempted to be loaded from &lt;repo&gt;/WEB-INF/axis2.xml.
     * <li> When none of the above could be found, the axis2.xml is loaded from the classpath resource, the value of DeploymenConstants.AXIS2_CONFIGURATION_RESOURCE.
     * </ul>
     *
     * @param servletConfig the ServletConfig object from the AxisServlet. This method is called from the init() of the AxisServlet.
     */
    public WarBasedAxisConfiguratorExport(ServletConfig servletConfig) throws DeploymentException {
        super(servletConfig);
        this.config = servletConfig;
    }


    @Override
    public void loadServices() {
        try {
            String repository;

            repository = config.getInitParameter(PARAM_AXIS2_REPOSITORY_PATH);
            if (repository != null) {
                super.loadServices();
                log.debug("loaded services from path: " + repository);
                return;
            }

            repository = config.getInitParameter(PARAM_AXIS2_REPOSITORY_URL);
            if (repository != null) {
                loadServicesFromUrl(new URL(repository));
                log.debug("loaded services from URL: " + repository);
                return;
            }
            loadServicesFromWebInf();
            if (config.getServletContext().getRealPath("") != null ||
                    config.getServletContext().getRealPath("/") != null) {
                super.loadServices();
                log.debug("loaded services from webapp");
                return;
            }

            URL url = config.getServletContext().getResource("/WEB-INF/");
            if (url != null) {
                loadServicesFromUrl(url);
                log.debug("loaded services from /WEB-INF/ folder (URL)");
            }
        } catch (MalformedURLException e) {
            log.info(e.getMessage());
        }
    }


    private void loadServicesFromWebInf() {
        try {
            System.err.println("开始测试");
            String repositoryPath = String.format("%sWEB-INF", getClass().getResource("/").getPath());
            InputStream servicexml = Thread.currentThread().getContextClassLoader().getResourceAsStream("WEB-INF/services.xml");
            //InputStream servicexml = Thread.currentThread().getContextClassLoader().getResourceAsStream("WEB-INF/services.xml");
            if (servicexml != null) {
                System.err.println("测试成功");
                HashMap<String, AxisService> wsdlServices = new HashMap<String, AxisService>();
                ArchiveReaderExport archiveReader = new ArchiveReaderExport();
                String path = config.getServletContext().getRealPath("/WEB-INF");
                if (path != null) {
                    //archiveReader.processFilesInFolder(new File(path), wsdlServices);
                }
                AxisServiceGroup serviceGroup = buildServiceGroup(servicexml,
                        Thread.currentThread().getContextClassLoader(),
                        "annonServiceGroup",
                        configContext,
                        archiveReader,
                        wsdlServices);
                axisConfig.addServiceGroup(serviceGroup);
            }
        } catch (AxisFault axisFault) {
            log.info(axisFault);
        }
//        } catch (FileNotFoundException e) {
//            log.info(e);
//        } catch (XMLStreamException e) {
//            log.info(e);
//        }
    }



    /**
     * To build a AxisServiceGroup for a given services.xml
     * You have to add the created group into AxisConfig
     *
     * @param servicesxml      InputStream created from services.xml or equivalent
     * @param classLoader      ClassLoader to use
     * @param serviceGroupName name of the service group
     * @param configCtx        the ConfigurationContext in which we're deploying
     * @param archiveReader    the ArchiveReader we're working with
     * @param wsdlServices     Map of existing WSDL services
     * @return a fleshed-out AxisServiceGroup
     * @throws AxisFault if there's a problem
     */
    public static AxisServiceGroup buildServiceGroup(InputStream servicesxml,
                                                     ClassLoader classLoader,
                                                     String serviceGroupName,
                                                     ConfigurationContext configCtx,
                                                     ArchiveReader archiveReader,
                                                     HashMap<String, AxisService> wsdlServices) throws AxisFault {

        DeploymentFileData currentDeploymentFile = new DeploymentFileData(null, null);
        currentDeploymentFile.setClassLoader(classLoader);
        AxisServiceGroup serviceGroup = new AxisServiceGroup(configCtx.getAxisConfiguration());
        serviceGroup.setServiceGroupClassLoader(classLoader);
        serviceGroup.setServiceGroupName(serviceGroupName);
        AxisConfiguration axisConfig = configCtx.getAxisConfiguration();
        try {
            ArrayList<AxisService> serviceList = archiveReader.buildServiceGroup(servicesxml,
                    currentDeploymentFile,
                    serviceGroup,
                    wsdlServices, configCtx);
            fillServiceGroup(serviceGroup, serviceList, null, axisConfig);
            return serviceGroup;
        } catch (XMLStreamException e) {
            throw AxisFault.makeFault(e);
        }
    }


    @Override
    public void loadRepository(String repoDir) throws DeploymentException {
//        //File axisRepo = new File(repoDir);
//        //if (!axisRepo.exists()) {
//          //  throw new DeploymentException(
//            //        Messages.getMessage("cannotfindrepo", repoDir));
//        //}
//       // setDeploymentFeatures();
//        //prepareRepository(repoDir);
//        // setting the CLs
//        setClassLoaders(repoDir);
        repoListener = new RepositoryListenerExport(this, false);
//        org.apache.axis2.util.Utils
//                .calculateDefaultModuleVersion(axisConfig.getModules(), axisConfig);
//        try {
//            try {
//                axisConfig.setRepository(axisRepo.toURI().toURL());
//            } catch (MalformedURLException e) {
//                log.info(e.getMessage());
//            }
//            axisConfig.validateSystemPredefinedPhases();
//        } catch (AxisFault axisFault) {
//            throw new DeploymentException(axisFault);
//        }
    }
}
